/************************************************************
** Tim Huerter
** CS 235
** Final Project
** File name: studentList.c
** Description:   This package contains the methods for 
**                initializing and maintaining the student
**                linked list.
** 
************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "./studentList.h"

#define MAXSTUDENTS 1000

studentType head;
studentType* students[MAXSTUDENTS];
static studentType* activeStudent;

static int studentCount = 0;

studentType nullStudent() {
   studentType temp = {
      "\0",
      "\0",
      -1,
      NULL,
      NULL,
      NULL,
   };
   return temp;
}
      
/************************************************************
** function:      initStudentList
************************************************************/
studentType* initStudentList(studentType master) {
   head = master;
   head.prev = NULL;
   head.next = NULL;
   head.ident = -1;
   activeStudent = head.next;
   head.studentGrades = initGradeList();
	studentCount = 1;
   return &head;
}

/************************************************************
** function:      initUpdateHead
************************************************************/
void initUpdateHead(gradeType* gradeList) {
   head.studentGrades = gradeList;
}

/************************************************************
** function:      getMaster
************************************************************/
studentType* getMaster() {
   return &head;
}

/************************************************************
** function:      deallocateStudents
************************************************************/
void deallocateStudents() {
   studentType *temp = head.next;
   studentType *next;

   while (temp) {
      deallocateGrades(temp->studentGrades);
      next = temp->next;
      free(temp);
      temp = next;
   }
}

/************************************************************
** function:      totalStudents
************************************************************/
int totalStudents() {
   return (studentCount + 1);
}

/************************************************************
** function:      getFirstStudent
************************************************************/
studentType* getFirstStudent() {
   return head.next;
}

/************************************************************
** function:      getNextStudent
************************************************************/
studentType* getNextStudent(studentType* s) {
   return s->next;
}
/************************************************************
** function:      getPrevStudent
************************************************************/
studentType* getPrevStudent(studentType* s) {
   return s->prev;
}

/************************************************************
** function:      getActiveStudent
************************************************************/
studentType* getActiveStudent() {
   return activeStudent;
}

/************************************************************
** function:      setActiveStudent
************************************************************/
void setActiveStudent(studentType* std) {
   activeStudent = std;
}

/************************************************************
** function:      getStudent
************************************************************/
studentType* getStudent(int id) {
   studentType* temp = getFirstStudent();

   while(temp) {
      if(temp->ident == id) {
         setActiveStudent(temp);
         return temp;
      }
      temp = getNextStudent(temp);
   }
   return NULL;
}


/************************************************************
** function:      addStudent
************************************************************/
void addStudent(studentType student) {
   studentType* temp;
   studentType* current;
   studentType* previous;
   gradeType* dest;
   gradeType* source = head.studentGrades;
   gradeType tempGrade;
   
   int i = 0;

   student.ident = studentCount;
   student.next = NULL;
   student.studentGrades = initGradeList();
   dest = student.studentGrades;
   while(source) {
      memcpy(&tempGrade, source, sizeof(gradeType));
      tempGrade.grade = 0.0;
      addGrade(tempGrade, dest);
      source = getNextGrade(source);
   }
   current = getFirstStudent();
   if (current == NULL) {
      temp = (studentType*)malloc(sizeof(studentType));
      memcpy(temp, &student, sizeof(studentType));
      head.next = temp;
		temp->ident = studentCount;
      temp->prev = &head;
      temp->next = NULL;
   }
   else if (strcmp(current->lastname, student.lastname) >= 0) {
      temp = (studentType*)malloc(sizeof(studentType));
      memcpy(temp, current, sizeof(studentType));
      memcpy(current, &student, sizeof(studentType));
      current->prev = &head;
      current->next = temp;
      temp->prev = current;
   } else {
      temp = (studentType*)malloc(sizeof(studentType));
      memcpy(temp, &student, sizeof(studentType));
      previous = current;
      current = current->next;

      while (current) // != NULL)
      {
         if (strcmp(current->lastname,temp->lastname)<0) {
            previous = current;         
         } else {
            current->prev = temp;
            break;
         }
         current = current->next;
      }
      temp->next=previous->next;
      previous->next=temp;
      temp->prev = previous;
   }
   studentCount++;
}

/************************************************************
** function:      delStudent
************************************************************/
void delStudent(int id) {
   studentType* temp = getStudent(id);
   studentType* prev;
   studentType* next;

   if(temp) {
      prev = getPrevStudent(temp);
      next = getNextStudent(temp);
      printf("deleting ...\n");
      printStudent(temp);
         if(next) {
            prev->next = next;
            next->prev = prev;
         } else {
            prev->next = NULL;
         }
         free(temp);
   } else {
      printf("Could not find student to delete\n");
   }

}

/************************************************************
** function:      printStudent
************************************************************/
void printStudent(studentType *std) {
   printf("Student id %d: %s, %s\n", std->ident, std->lastname, std->firstname);
}

/************************************************************
** function:      printStudents
************************************************************/
int printStudents(studentType* std) {
   studentType *temp = std;
   int i=0;

   while (temp) {
      printStudent(temp);
      temp = getNextStudent(temp);
      i++; 
   }
   if(i < 1) {
      printf("No Students\n");
   }
   return i;
}


/************************************************************
** function:      editStudent
************************************************************/
studentType* editStudent(int id) {
   studentType *temp = getStudent(id);
   int opt;
   char str[MAXNAME];
	bool valid = false;
	bool valid2=false;

	while(!valid){
   	if(temp != NULL) {
   	   printf("Editing: ");
   	   printStudent(temp);
   	   printf("\nWould you like to update: \n");
   	   printf("Students Firstname [enter 1]\n");
   	   printf("Students Lastname  [enter 2]\n");
   	   printf("Students Grades    [enter 3]\n");
   	   printf("-> ");
   	   scanf("%d", &opt);
  	    
      	switch (opt) {
      	   case 1:
      	      printf("Please enter the firstname: ");
      	      scanf("%s", str);
      	      memset(temp->firstname, 0, MAXNAME);
      	      strcpy(temp->firstname, str);
      	      valid = true;
    	        break;
	         case 2:
	            printf("Please enter the lastname: ");
	            scanf("%s", str);
	            memset(temp->lastname, 0, MAXNAME);
	            strcpy(temp->lastname, str);
	            valid = true;
	            break;
	         case 3:
	            	printf("Grades:\n");
	            	printGrades(temp->studentGrades);
	            	printf("\nPlease enter the grade id you'd like to edit: ");
	            	if (scanf("%d", &opt) == 1){
	            		if (checkGradeID(temp->studentGrades, opt) == true) {
	            			(void) editGrade(opt, temp->studentGrades);
	            			valid = true;
	            		}
	            		else{
	            			invalidEntry();
	          	  		}
	            	}
	            	else{
	            		invalidEntry();
	            	}
	            break;
	         default:
					invalidEntry();
	            break;
	      }
	   } else {
			invalidEntry();
   	}
   	getchar();  // clear the \n from the buffer
   }
   return temp;
}

bool checkStdID(studentType* std, int selection){
	studentType *temp = std;
   bool result = false;

   while (temp) {
      if (temp->ident == selection) {
      	result = true;
      }
      temp = getNextStudent(temp);
   }
   return result;
}



